package com.mogu_soup.game;

import com.mogu_soup.entity.Bullet;
import com.mogu_soup.entity.Entity;
import com.mogu_soup.entity.Tank;
import com.mogu_soup.map.Brick;
import com.mogu_soup.map.GameMap;
import com.mogu_soup.util.Constant;
import com.mogu_soup.util.MyMusic;
import com.mogu_soup.util.MyUtil;
import com.mogu_soup.util.TankPool;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.Vector;

import static com.mogu_soup.util.Constant.*;
import static java.awt.event.KeyEvent.*;

/**
 * Version: 2.1
 * Author: TangJun
 * Date: 2024-08-02
 * Note: 游戏窗口的设置
 */
public class GameFrame extends JFrame implements Runnable{
    public static int titleHeight;//窗口标题栏高度
    private static int gameState;//当前游戏状态，静态方便在其他类中修改
    private int choose;//游戏菜单的选项
    private Tank hero;//我方坦克
    private Vector<Tank> enemies;//敌人坦克
    private static int enemyKill;//敌人击杀数量
    private static int enemyBorn;//敌人生成数量
    private static Vector<Recorder.Node> nodes;//记录所有坦克坐标
    public static int level = 1;//当前关卡
    private GameMap gameMap;
    private BufferedImage bufImg = new BufferedImage(FRAME_WIDTH, FRAME_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR);//创建缓冲图片

    //构造方法
    public GameFrame() {
        initFrame();
        initListener();
        initGame();
        new Thread(this).start();
    }

    //初始化窗口
    private void initFrame() {
        //设置窗口标题
        this.setTitle(FRAME_TITLE);
        //设置窗口大小
        this.setSize(FRAME_WIDTH, FRAME_HEIGHT);
        //设置窗口位置
        this.setLocation(FRAME_X, FRAME_Y);
        //设置窗口大小不可变
        this.setResizable(false);
        //显示窗口
        this.setVisible(true);
        titleHeight = getInsets().top;
    }

    //初始化游戏
    private void initGame() {
        gameState = STATE_INIT;
    }


    //初始化事件监听
    private void initListener() {
        //窗口监听
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                Recorder.Save();//保存数据
                System.exit(0);
            }
        });
        //键盘监听
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int keyCode = e.getKeyCode();
                switch (gameState) {
                    case STATE_INIT:
                        keyEventMenu(keyCode);
                        break;
                    case STATE_RUN:
                        keyEventRun(keyCode);
                        break;
                    case STATE_HELP:
                        keyEventHelp(keyCode);
                        break;
                    case STATE_ABOUT:
                        keyEventAbout(keyCode);
                        break;
                    case STATE_WIN:
                    case STATE_OVER:
                        keyEventOver(keyCode);
                        break;
                    default:
                        break;
                }
            }

            //游戏结束的按键监听
            private void keyEventOver(int keyCode) {
                //重置游戏（坦克，子弹，爆炸效果等）
                resetGame();
                level = 1;
                if (keyCode == VK_ESCAPE) {
                    System.exit(0);
                } else if (keyCode == VK_ENTER) {
                    gameState = STATE_INIT;
                }
            }

            //游戏关于的按键监听
            private void keyEventAbout(int keyCode) {
                gameState = STATE_INIT;
            }

            //游戏帮助的按键监听
            private void keyEventHelp(int keyCode) {
                gameState = STATE_INIT;
            }

            //游戏运行时的按键监听
            private void keyEventRun(int keyCode) {
                switch (keyCode) {
                    case VK_UP:
                    case VK_W:
                        hero.setDir(Tank.DIR_UP);
                        hero.move();
                        break;
                    case VK_DOWN:
                    case VK_S:
                        hero.setDir(Tank.DIR_DOWN);
                        hero.move();
                        break;
                    case VK_LEFT:
                    case VK_A:
                        hero.setDir(Tank.DIR_LEFT);
                        hero.move();
                        break;
                    case VK_RIGHT:
                    case VK_D:
                        hero.setDir(Tank.DIR_RIGHT);
                        hero.move();
                        break;
                    case VK_J:
                    case VK_ENTER:
                        hero.fire();
                        break;
                    default:
                        break;
                }
            }

            //菜单选择时的按键监听
            private void keyEventMenu(int keyCode) {
                switch (keyCode) {
                    case VK_UP:
                    case VK_W:
                        if (--choose < 0) {
                            choose = MENU.length - 1;
                        }
                        break;
                    case VK_DOWN:
                    case VK_S:
                        if (++choose > MENU.length - 1) {
                            choose = 0;
                        }
                        break;
                    case VK_ENTER:
                        enter();
                        break;
                    default:
                        break;
                }
            }
        });
    }

    //菜单栏确认
    private void enter() {
        switch (choose) {
            case 0:
                newGame();
            break;
            case 1:
                continueGame();
                break;
            case 2:
                gameState = STATE_HELP;
                break;
            case 3:
                gameState = STATE_ABOUT;
                break;
            case 4:
                System.exit(0);
                break;
        }
    }

    //开始新游戏
    private void newGame() {
        Recorder.setLastLevel(level);
        Recorder.setKillNum(0);
        //初始化
        gameState = STATE_RUN;
        enemyKill = 0;
        enemyBorn = 0;
        //创建地图
        gameMap = new GameMap();
        //创建我方坦克
        hero = new Tank(Tank.DEFAULT_SIZE / 2 + 20, FRAME_HEIGHT - Tank.DEFAULT_SIZE / 2, Tank.DIR_UP);
        hero.setEnemy(false);
        //创建敌方坦克
        enemies = new Vector<Tank>();
        //创建一个线程生成敌方坦克
        new Thread() {
            @Override
            public void run() {
                while (gameState == STATE_RUN) {
                    //不足最大数量就生成
                    if (enemyBorn < LevelInfo.getInstance().getEnemyNum()
                        && enemies.size() < ENEMY_MAX_NUM) {
                        int x = MyUtil.getRandomInt(Tank.DEFAULT_SIZE / 2, FRAME_HEIGHT - Tank.DEFAULT_SIZE / 2);
                        int y = Tank.DEFAULT_SIZE / 2 + titleHeight + Tank.DEFAULT_SIZE;
                        Tank enemy = TankPool.removeTank();
                        enemy.set(x, y, Entity.DIR_DOWN);
                        new Thread(enemy).start();//每一个坦克就是一个线程
                        enemies.add(enemy);
                        enemyBorn++;
                    }
                    try {
                        Thread.sleep(ENEMY_BORN_INTERVAL);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }.start();
        //播放音乐
        MyMusic.PlayMusic();
        //保存关卡数据
        Recorder.setTanks(enemies);
        System.out.println(Recorder.getTanks());
    }

    //继续上局游戏
    private void continueGame() {
        Recorder.Load();
        //初始化
        gameState = STATE_RUN;
        enemyKill = Recorder.getDestroyNum();
        enemyBorn = Recorder.getNodes().size();
        level = Recorder.getLastLevel();
        //创建地图
        gameMap = new GameMap();
        //创建我方坦克
        hero = new Tank(Tank.DEFAULT_SIZE / 2 + 20, FRAME_HEIGHT - Tank.DEFAULT_SIZE / 2, Tank.DIR_UP);
        hero.setEnemy(false);
        //创建敌方坦克
        enemies = new Vector<Tank>();
        //创建一个线程生成敌方坦克
        new Thread() {
            @Override
            public void run() {
                //加载现有的坦克
                for (Recorder.Node node : Recorder.getNodes()) {
                    Tank enemy = TankPool.removeTank();
                    enemy.set(node.getX(), node.getY(), node.getDirect());
                    new Thread(enemy).start();
                    enemies.add(enemy);
                }
                while (gameState == STATE_RUN) {
                    //不足最大数量就生成
                    if (enemyBorn < LevelInfo.getInstance().getEnemyNum()
                            && enemies.size() < ENEMY_MAX_NUM) {
                        int x = MyUtil.getRandomInt(Tank.DEFAULT_SIZE / 2, FRAME_HEIGHT - Tank.DEFAULT_SIZE / 2);
                        int y = Tank.DEFAULT_SIZE / 2 + titleHeight + Tank.DEFAULT_SIZE;
                        Tank enemy = TankPool.removeTank();
                        enemy.set(x, y, Entity.DIR_DOWN);
                        new Thread(enemy).start();//每一个坦克就是一个线程
                        enemies.add(enemy);
                        enemyBorn++;
                    }
                    try {
                        Thread.sleep(ENEMY_BORN_INTERVAL);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }.start();
        //播放音乐
        MyMusic.PlayMusic();

    }


    //重置游戏
    private void resetGame(){
        //重置菜单选项
        choose = 0;
        //重置敌方坦克
        for (Tank enemy : enemies) {
            enemy.ReturnBullets();
            enemy.ReturnBombs();
        }
        enemies.clear();
        //重置我方坦克
        hero.ReturnBombs();
        hero.ReturnBullets();
        //重置地图
        gameMap.ReturnMap();

    }


    @Override
    public void paint(Graphics g1) {
        Graphics g = bufImg.getGraphics();//得到缓冲图片画笔
        switch (gameState) {
            case STATE_INIT:
                drawMenu(g);
                break;
            case STATE_RUN:
                drawRun(g);
                break;
            case STATE_HELP:
                drawHelp(g);
                break;
            case STATE_ABOUT:
                drawAbout(g);
                break;
            case STATE_WIN:
            case STATE_OVER:
                drawOver(g);
                break;
            default:
                break;
        }
        g1.drawImage(bufImg, 0, 0, this);//将缓冲图片绘制到窗口
    }

    //过关
    private void CrossLevel(){
        if (enemyKill >= LevelInfo.getInstance().getEnemyNum()) {
            if (level == LevelInfo.levelNum) {
                gameState = STATE_WIN;
                System.out.println("加一次");
                return;
            }
            level++;
            gameState = STATE_CROSS;
            resetGame();
            newGame();
        }
    }


    //绘制菜单
    private void drawMenu(Graphics g) {
        //画背景
        g.setColor(Color.black);
        g.drawImage(FRAME_BACKGROUND, 0, 0, FRAME_WIDTH, FRAME_HEIGHT, this);
        //画菜单
        g.setFont(FRAME_FONT);
        final int DIS = 100;//字体间距
        final int LENGTH = 8;//字体长度
        int x = (FRAME_WIDTH - LENGTH >>> 1) - 100;
        int y = (FRAME_HEIGHT >>> 2) + 150;
        //画标题
        g.drawImage(GAME_TITLE, 50, -200, FRAME_WIDTH, FRAME_WIDTH / 2 , this);
        for (int i = 0; i < MENU.length; i++) {
            if (choose == i) {
                g.setColor(Color.red);
            } else {
                g.setColor(Color.white);
            }
            g.drawString(MENU[i], x, y + DIS * i);
        }
    }

    //绘制运行时图片
    private void drawRun(Graphics g) {
        //先屏幕清空
        g.setColor(Color.white);
        g.fillRect(0, 0, FRAME_WIDTH, FRAME_HEIGHT);
        //绘制背景和图片
        g.drawImage(GAME_BACKGROUND, 0, 0, FRAME_HEIGHT, FRAME_HEIGHT, this);
        //绘制地图碰撞层
        gameMap.draw(g);
        //判断坦克与砖块碰撞
        tankCollideBrick();
        //判断坦克与坦克碰撞
        tankCollideTank();
        //判断坦克与子弹碰撞
        bulletCollideTank();
        //判断砖块与子弹碰撞
        bulletCollideBrick();
        //绘制坦克
        drawEnemies(g);
        hero.draw(g);
        //绘制地图覆盖层
        gameMap.drawCover(g);
        //绘制战绩信息
        drawInfo(g);
    }
    //绘制战绩信息
    private void drawInfo(Graphics g) {
        g.setColor(Color.black);
        g.setFont(INFO_FONT);
        g.drawString("关卡：" + level, FRAME_HEIGHT + Tank.DEFAULT_SIZE, FRAME_HEIGHT / 3 - 100);
        g.drawImage(Tank.ENEMY[0], FRAME_HEIGHT + Tank.DEFAULT_SIZE, FRAME_HEIGHT / 3,
                Tank.DEFAULT_SIZE, Tank.DEFAULT_SIZE, this);
        g.setColor(Color.red);
        g.drawString( "" + enemyKill , FRAME_HEIGHT + Tank.DEFAULT_SIZE + 150, FRAME_HEIGHT / 3 + 60);
    }

    //判断坦克与坦克碰撞
    private void tankCollideTank() {
        hero.collideTanks(enemies);
        for (Tank enemy : enemies) {
            enemy.collideTanks(enemies);
            enemy.collideTank(hero);
        }
    }

    //判断坦克与砖块碰撞
    private void tankCollideBrick() {
        hero.collideBricks(gameMap.getBricks());
        for (Tank enemy : enemies) {
            enemy.collideBricks(gameMap.getBricks());
        }
    }

    //判断子弹与砖块碰撞
    private void bulletCollideBrick() {
        gameMap.bulletsCollideAll(hero.getBullets());//我方坦克
        for (Tank enemy : enemies) {
            gameMap.bulletsCollideAll(enemy.getBullets());//敌方坦克
        }
    }

    //判断子弹与坦克碰撞
    private void bulletCollideTank() {
        for (Tank enemy : enemies) {
            enemy.collideBullets(hero.getBullets());//敌方坦克
            hero.collideBullets(enemy.getBullets());//我方坦克
        }
    }

    //绘制敌方坦克
    private void drawEnemies(Graphics g) {
        for (int i = 0; i < enemies.size(); i++) {
            Tank enemy = enemies.get(i);
            if (enemy.isLive()) {
                enemy.draw(g);//绘制存活的坦克
            } else {
                /*//绘制摧毁效果
                g.drawImage(Bomb.DESTROY, enemy.getX() - enemy.getSize() / 2, enemy.getY() - enemy.getSize() / 2,
                        enemy.getSize(), enemy.getSize(),this);
                System.out.println("摧毁");*/
                TankPool.addTank(enemies.remove(i));//移除销毁的坦克
                i--;
                enemyKill++;
                Recorder.setKillNum(enemyKill);
                CrossLevel();
            }
        }
    }



    //绘制游戏帮助
    private void drawHelp(Graphics g) {
        g.setColor(Color.black);
        g.fillRect(0, 0, FRAME_WIDTH, FRAME_HEIGHT);


        final int dis = 50;
        g.setColor(Color.white);
        g.setFont(HELP_FONT_BIG);
        g.drawString(HELP_STR0, FRAME_WIDTH / 3 + dis * 3, FRAME_HEIGHT / 3);
        g.setFont(HELP_FONT_SMALL);
        g.drawString(HELP_STR1, FRAME_WIDTH / 3 + 2*dis - 20, FRAME_HEIGHT / 3 + 3*dis);
        g.drawString(HELP_STR2, FRAME_WIDTH / 3 - 20, FRAME_HEIGHT / 3 + 5*dis);

        g.setColor(Color.white);
        g.setFont(OVER_FONT);
        g.drawString(HINT_STR, 10, FRAME_HEIGHT - 20);
    }

    //绘制游戏关于
    private void drawAbout(Graphics g) {
        g.setColor(Color.black);
        g.fillRect(0, 0, FRAME_WIDTH, FRAME_HEIGHT);


        final int dis = 50;
        g.setColor(Color.white);
        g.setFont(HELP_FONT_BIG);
        g.drawString(ABOUT_STR0, FRAME_WIDTH / 3 + dis * 3, FRAME_HEIGHT / 3);
        g.setFont(HELP_FONT_SMALL);
        g.drawString(ABOUT_STR1, FRAME_WIDTH / 3 - 20, FRAME_HEIGHT / 3 + 2*dis);
        g.drawString(ABOUT_STR2, FRAME_WIDTH / 3 - 20, FRAME_HEIGHT / 3 + 3*dis);

        g.setColor(Color.white);
        g.setFont(OVER_FONT);
        g.drawString(HINT_STR, 10, FRAME_HEIGHT - 20);
    }

    //绘制游戏结束时图片
    private void drawOver(Graphics g) {
        g.drawImage(GAME_BACKGROUND, 0, 0, FRAME_HEIGHT, FRAME_HEIGHT, this);
        if (gameState == STATE_OVER) {
            g.drawImage(GAME_OVER, 0, 0, FRAME_HEIGHT, FRAME_HEIGHT, this);
        } else  if (gameState == STATE_WIN){
            g.drawImage(GAME_WIN, 0, 0, FRAME_HEIGHT, FRAME_HEIGHT, this);
        }
        g.setColor(Color.white);
        g.setFont(OVER_FONT);
        g.drawString(OVER_STR0, 10, FRAME_HEIGHT - 20);
        g.drawString(OVER_STR1, FRAME_HEIGHT - 260, FRAME_HEIGHT - 20);
    }

    public static void setGameState(int gameState) {
        GameFrame.gameState = gameState;
    }

    //刷新窗口界面
    @Override
    public void run() {
        while (true) {
            repaint();
            try {
                Thread.sleep(1000 / FPS);
            } catch (InterruptedException e) {
                System.out.println("休眠时异常");
                e.printStackTrace();
                break;
            }
        }
    }
}


